package cn.green.core.components.dialect.impls.mysql.dialects;

import cn.green.core.common.enums.field.ColumnType;
import cn.green.core.components.dialect.DatabaseDdlDialect;
import cn.green.core.components.dialect.impls.mysql.grammar.MysqlGrammars;
import cn.green.core.components.entity.ColumnLength;
import cn.green.core.components.exceptions.QDdlException;
import cn.green.core.components.field.FieldFormTypeCom;
import cn.green.core.components.field.FieldTypeCom;
import cn.green.core.components.setter.PrimaryKey;
import cn.green.core.components.store.field.FieldFormTypeStore;
import cn.green.core.components.store.field.FieldTypeStore;
import cn.green.core.components.store.table.TableTypeStore;
import cn.green.core.components.table.TableTypeCom;
import cn.green.core.model.QField;
import cn.green.core.model.QTable;

import java.util.List;

/**
 * @author wang.yishu
 * @version 1.0
 * @className MysqlDdlDialect
 * @description mysql方言
 * @date 2024/11/15 13:44
 */
public class MysqlDdlDialect implements DatabaseDdlDialect {
    @Override
    public String crtTableSql(QTable table) {
        if (table == null) {
            throw new QDdlException("mysql ddl language executes error : table structure is null.");
        }
        String tableName = table.getTableName();
        StringBuilder sql = new StringBuilder(
                MysqlGrammars.DDL.CREATE
                        + MysqlGrammars.SYMBOL.BLANKET
                        + MysqlGrammars.DDL.TABLE
                        + MysqlGrammars.SYMBOL.BLANKET
                        + tableName + MysqlGrammars.SYMBOL.BLANKET + MysqlGrammars.SYMBOL.BRACKET_LEFT);
        String tableType = table.getTableType();
        TableTypeCom tableTypeCom = TableTypeStore.get(tableType);
        //固定字段
        List<QField> fields = table.initialFields();
        QField primaryKey = tableTypeCom.getPrimaryKeyField();
        String primaryKeyName = primaryKey.getFieldName();
        PrimaryKey primaryKeyType = tableTypeCom.getPrimaryKey();
        StringBuilder defineFieldSql = new StringBuilder();
        for (QField field : fields) {
            if (field.canBeInTable()) {
                this.buildDefineFieldSql(field, primaryKeyName.equals(field.getFieldName()), primaryKeyType, defineFieldSql);
            }
        }
        if (defineFieldSql.length() == 0) {
            throw new QDdlException("mysql ddl language executes error : no field can be defined.");
        }
        defineFieldSql = new StringBuilder(defineFieldSql.substring(0, defineFieldSql.length() - 1));
        sql.append(defineFieldSql);
        sql.append(MysqlGrammars.SYMBOL.BRACKET_RIGHT);
        String tableAliasName = table.getTableAliasName();
        if (tableAliasName != null && !tableAliasName.isEmpty()) {
            sql.append(MysqlGrammars.SYMBOL.BLANKET).append(MysqlGrammars.DDL.COMMENT).append(MysqlGrammars.SYMBOL.S_QT_MARK).append(tableAliasName)
                    .append(MysqlGrammars.SYMBOL.S_QT_MARK);
        }
        sql.append(MysqlGrammars.SYMBOL.BLANKET).append(MysqlGrammars.SYMBOL.SEMICOLON);
        return sql.toString();
    }

    private void buildDefineFieldSql(QField field, boolean isPrimaryKey, PrimaryKey primaryKeyType, StringBuilder sql) {
        //字段名称
        String fieldName = field.getFieldName();
        //字段别名
        String aliasName = field.getAliasName();
        //字段类型
        String fieldType = field.getFieldType();
        FieldTypeCom fieldTypeCom = FieldTypeStore.get(fieldType);
        if (fieldTypeCom.isVirtual()) {
            return;
        }
        //字段数据库类型
        ColumnType columnType = fieldTypeCom.getColumnType();
        //字段长度
        ColumnLength columnLength = fieldTypeCom.defaultColumnLength();
        if (columnLength == null) {
            columnLength = new ColumnLength(20, 0);
        }
        String fieldForm = field.getFieldForm();
        FieldFormTypeCom fieldFormTypeCom = FieldFormTypeStore.get(fieldForm);
        if (fieldFormTypeCom != null && fieldFormTypeCom.columnLength() != null) {
            columnLength = fieldFormTypeCom.columnLength();
        }
        //数据库真实字段类型
        String databaseColumnType = MysqlGrammars.transform(columnType, columnLength.getIntegerLength(), columnLength.getDecimalLength());
        String fieldSql = MysqlGrammars.SYMBOL.P + fieldName + MysqlGrammars.SYMBOL.P + MysqlGrammars.SYMBOL.BLANKET
                + databaseColumnType + MysqlGrammars.SYMBOL.BLANKET  + (isPrimaryKey ? MysqlGrammars.primary(primaryKeyType.primarySetter()) : "")
                + MysqlGrammars.DDL.COMMENT + MysqlGrammars.SYMBOL.BLANKET
                + MysqlGrammars.SYMBOL.S_QT_MARK + aliasName + MysqlGrammars.SYMBOL.S_QT_MARK + MysqlGrammars.SYMBOL.BLANKET
                + (isPrimaryKey ? MysqlGrammars.DDL.PRIMARY_KEY : "") + MysqlGrammars.SYMBOL.COMMA;
        sql.append(fieldSql);
    }

    @Override
    public String drpTableSql(String tableName) {
        /*
        todo QTable组件不允许删表
         */
        throw new QDdlException("mysql ddl language executes error : QTable can't drop table.");
    }

    @Override
    public String addFieldSql(QField field) {
        StringBuilder rtn = new StringBuilder();
        this.buildAddFieldSql(field, rtn);
        return rtn.toString();
    }

    private void buildAddFieldSql(QField field, StringBuilder sql) {
        if (field == null) {
            throw new QDdlException("mysql ddl language executes error : field structure is null.");
        }
        String tableName = field.getTableName();
        if (tableName == null || "".equals(tableName)) {
            throw new QDdlException("mysql ddl language executes error : field's table name is null.");
        }
        String fieldName = field.getFieldName();
        //字段别名
        String aliasName = field.getAliasName();
        //字段类型
        String fieldType = field.getFieldType();
        FieldTypeCom fieldTypeCom = FieldTypeStore.get(fieldType);
        if (fieldTypeCom.isVirtual()) {
            return;
        }
        //字段数据库类型
        ColumnType columnType = fieldTypeCom.getColumnType();
        //字段长度
        ColumnLength columnLength = fieldTypeCom.defaultColumnLength();
        if (columnLength == null) {
            columnLength = new ColumnLength(200, 0);
        }
        String fieldForm = field.getFieldForm();
        FieldFormTypeCom fieldFormTypeCom = FieldFormTypeStore.get(fieldForm);
        if (fieldFormTypeCom != null && fieldFormTypeCom.columnLength() != null) {
            columnLength = fieldFormTypeCom.columnLength();
        }
        //数据库真实字段类型
        String databaseColumnType = MysqlGrammars.transform(columnType, columnLength.getIntegerLength(), columnLength.getDecimalLength());
        String fieldSql = MysqlGrammars.DDL.ALTER + MysqlGrammars.SYMBOL.BLANKET + MysqlGrammars.DDL.TABLE +  MysqlGrammars.SYMBOL.BLANKET + tableName + MysqlGrammars.SYMBOL.BLANKET + MysqlGrammars.DDL.ADD
                + MysqlGrammars.SYMBOL.BLANKET + MysqlGrammars.DDL.COLUMN + MysqlGrammars.SYMBOL.BLANKET
                + MysqlGrammars.SYMBOL.P + fieldName + MysqlGrammars.SYMBOL.P + MysqlGrammars.SYMBOL.BLANKET
                + databaseColumnType + MysqlGrammars.SYMBOL.BLANKET + MysqlGrammars.DDL.COMMENT + MysqlGrammars.SYMBOL.BLANKET
                + MysqlGrammars.SYMBOL.S_QT_MARK + aliasName + MysqlGrammars.SYMBOL.S_QT_MARK + MysqlGrammars.SYMBOL.SEMICOLON;
        sql.append(fieldSql);
    }

    @Override
    public String updFieldSql(QField field) {
        /*
           todo 当前组件只准许修改字段名称和字段别名
         */
        String tableName = field.getTableName();
        if (tableName == null || "".equals(tableName)) {
            throw new QDdlException("mysql ddl language executes error : table name is null!");
        }
        String oldColumnName = field.getOldFieldName();
        String newColumnName = field.getFieldName();
        String newColumnAlias = field.getAliasName();
        return MysqlGrammars.DDL.ALTER + MysqlGrammars.SYMBOL.BLANKET
                + MysqlGrammars.DDL.TABLE + MysqlGrammars.SYMBOL.BLANKET + tableName + MysqlGrammars.SYMBOL.BLANKET
                + MysqlGrammars.DDL.CHANGE +
                MysqlGrammars.SYMBOL.BLANKET + oldColumnName + MysqlGrammars.SYMBOL.BLANKET + newColumnName + MysqlGrammars.SYMBOL.BLANKET +
                MysqlGrammars.DDL.COMMENT + "'" + newColumnAlias + "'" + MysqlGrammars.SYMBOL.SEMICOLON;
    }

    @Override
    public String delFieldSql(QField field) {
         /*
           todo QTable不允许删除字段
         */
        throw new QDdlException("mysql ddl language executes error : QTable can't delete column.");
    }

}
